﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using SFML.Graphics;
using SFML.Window;

namespace Theta.Animations
{
    [Serializable]
    public class Animation : ISerializable
    {
        internal int CurIndex;

        Frame[] _frames;
        double _curFrameLifetime;
        bool _loop;

        public Vector2i FrameSize { get; set; }

        public bool Loop
        {
            get { return _loop; }
            set
            {
                _loop = value;
                if (Ended)
                    Ended = false;
            }
        }

        public bool Ended { get; set; }

        public Frame CurrentFrame
        {
            get { return _frames[CurIndex]; }
        }

        public Animation(List<Frame> frames, Vector2i frameSize, bool loop)
            : this(frames.ToArray(), frameSize, loop)
        {
        }

        public Animation(Frame[] frames, Vector2i frameSize, bool loop)
        {
            _frames = frames;
            FrameSize = frameSize;
            Loop = loop;
        }

        public Animation(SerializationInfo info, StreamingContext context)
        {
            _frames = (Frame[])info.GetValue("_frames", typeof(Frame[]));
            FrameSize = (Vector2i)info.GetValue("FrameSize", typeof(Vector2i));
        }

        public void SetFramesLifetimes(double newLifetime)
        {
            for(int i = 0; i < _frames.Length; i++)
            {
                Frame s = _frames[i];
                s.Lifetime = newLifetime;
                _frames[i] = s;
            }
        }

        public void Update(TimeSpan elapsedTime)
        {
            if(Ended && !Loop)
                return;

            _curFrameLifetime += elapsedTime.TotalSeconds;
            if (_curFrameLifetime >= CurrentFrame.Lifetime)
            {
                if (CurIndex + 1 < _frames.Length)
                    CurIndex++;
                else if (Loop)
                    CurIndex = 0;
                else
                    Ended = true;

                Console.WriteLine("Frames switched: " +  _curFrameLifetime);
                _curFrameLifetime = 0;
            }
        }

        public IntRect GetRect()
        {
            return CurrentFrame.GetRect(FrameSize);
        }

        public Animation Copy()
        {
            //The frame array will be passed as a value type (it's a struct) 
            //Or not.
            Frame[] newFrames = new Frame[_frames.Length];

            for(int i = 0; i < _frames.Length; i++)
            {
                Frame f = _frames[i];
                newFrames[i] = f;
            }

            Animation a = new Animation(newFrames, new Vector2i(FrameSize.X, FrameSize.Y), Loop);
            return a;
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("_frames", _frames, typeof(Frame[]));
            info.AddValue("FrameSize", FrameSize, typeof(Vector2i));
        }
    }
}
